<script lang="ts" setup>
import {onMounted, ref} from 'vue'

defineOptions({
	name: 'BaseNotice'
})
const props = defineProps({
	icon: {// 显示图标
		type: String,
		default: 'ph:speaker-high-fill'
	},
	iconColor: { // 图标颜色
		type: String,
		default: '#f9ae3d'
	},
	iconSize: { // 图标大小
		type: Number,
		default: 22
	},
	noticeList: { // 数据
		type: Array,
		default() {
			return []
		}
	},
	speed: { // 速度
		type: Number,
		default: -1
	},
	txtColor: {
		type: String,
		default: '#f9ae3d'
	},
	txtProps: {
		type: String,
		default: 'content'
	},
	width: {
		type: String,
		default: '300px'
	},
	height: {
		type: String,
		default: '30px'
	},
	bgCol: { // 背景色
		type: String,
		default: '#fdf6ec'
	}
})

const current = ref(0)
onMounted(() => {
	notice('txtBox', 'txt' + current.value, props.speed)
})

const again = () => {
	current.value = current.value + 1
	if (current.value >= props.noticeList.length) {
		current.value = 0
	}
	notice('txtBox', 'txt' + current.value, props.speed)
}

/**
 * @description 滚动公告功能
 * @function notice
 * @param {string} meq - 公告外部容器的ID
 * @param {string} text - 实际滚动的公告内容的ID
 * @param {number} speed - 滚动速度，通常为负值，表示向左滚动
 */
const notice = (meq: string, text: string, speed: number) => {
	// 通过ID获取对应的DOM元素
	let [
		meqEl = document.getElementById(meq)!,    // 外部容器
		meqElText = document.getElementById(text)!,  // 公告内容
		timer = null as any // 定时器
	] = []

	// 设置公告内容的初始位置，使其完全在外部容器的右侧
	meqElText.style.left = meqEl.offsetWidth + 'px'
	// 清除之前可能存在的定时器
	clearInterval(timer)
	// 创建一个新的定时器，用于控制滚动效果
	timer = setInterval(noticeFn, 15)

	function noticeFn() {
		// 如果公告内容的左边界已经完全超出了外部容器的左侧
		if (meqElText.offsetLeft < -meqElText.offsetWidth) {
			// 重新设置公告内容的位置，使其回到外部容器的右侧
			meqElText.style.left = meqEl.offsetWidth + 'px'
			clearInterval(timer)
			again()
		}
		// 实现滚动效果
		meqElText.style.left = meqElText.offsetLeft + speed + 'px'
	}

	// 当鼠标悬停在公告内容上时，停止滚动
	meqElText.onmouseover = function () {
		clearInterval(timer)
	}
	// 当鼠标离开公告内容时，继续滚动
	meqElText.onmouseout = function () {
		timer = setInterval(noticeFn, 15)
	}
	// 当鼠标按下时，可以拖动公告内容
	meqElText.onmousedown = function (e) {
		const ev = e || window.event
		// 计算鼠标与公告内容左边界的距离
		let disX = ev.clientX - meqElText.offsetLeft
		// 鼠标移动时，公告内容跟随鼠标移动
		meqElText.onmousemove = function (e) {
			const ev = e || window.event
			meqElText.style.left = ev.clientX - disX + 'px'
		}
		// 鼠标松开时，停止拖动公告内容
		document.onmouseup = function () {
			meqElText.onmousemove = null
		}
	}
}
</script>

<template>
	<div
		:style="{
			width: props.width,
			height: props.height,
			lineHeight: props.height,
			backgroundColor: props.bgCol
		}"
		class="notice"
	>
		<base-icon
			:color="iconColor"
			:icon="props.icon"
			:size="props.iconSize"
			:style="{lineHeight: props.height}"
			class="notice-icon"
		/>
		<div id="txtBox" class="notice-box">
			<div
				v-for="(item, index) in noticeList"
				v-show="current === index"
				:id="'txt' + index"
				:key="index"
				:style="{color: props.txtColor}"
				class="notice-box-txt"
			>
				{{ item?.[props.txtProps] }}
			</div>
		</div>
	</div>
</template>

<style lang="scss" scoped>
.notice {
	margin: 0 10px;
	display: flex;
	overflow: hidden;
	align-items: center;
	border-radius: 5px;

	&-icon {
		margin: 0 5px;
	}

	&-box {
		width: 100%;
		height: inherit;
		position: relative;
		overflow: hidden;

		&-txt {
			white-space: nowrap;
			position: absolute;
		}
	}
}
</style>
